package org.ricks.common.conf;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;

/**
 * @author chenwei
 * @Title:
 * @Package
 * @Description:
 * @date 2020/8/716:59
 */
public class ConfClassProcessor extends org.ricks.common.conf.AbstractConfProcessor {

    private ConfClassProcessor() {
    }

    private static class ConfClassProcessorInner {
        private static ConfClassProcessor confClassProcessor = new ConfClassProcessor();
    }

    public static ConfClassProcessor getProcessor() {
        return ConfClassProcessorInner.confClassProcessor;
    }

    @Override
    public void process() {
        classSet.forEach(clazz -> putInConf(org.ricks.common.conf.SourceHandler.getSourceHandler().getSourceByClass(clazz), clazz));
    }

    public void putInConf(Object oo, Class<?> clazz) {
        String prefix = "";
        if (!clazz.isAnnotationPresent(ConfProperties.class)) {
            return;
        }
        prefix = clazz.getAnnotation(ConfProperties.class).prefix();
        if (prefix.endsWith(".")) {
            prefix = prefix.substring(0, prefix.length() - 1);
        }
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String tmpPrefix = prefix + "." + field.getName();
            String[] props = tmpPrefix.split("\\.");
            putInConfCore(oo, props, field);
        }
    }

    public void putInConfCore(Object o, String[] props, Field field) {
        int ind = 0;
        while (true) {
            if (ind < props.length && Objects.nonNull(o) && o instanceof Map) {
                o = ((Map<?, ?>) o).get(props[ind]);
            } else {
                break;
            }
            ind++;
        }

        if (Objects.isNull(o)) {
            return;
        }

        try {
            field.setAccessible(true);
            field.set(field, conver(String.valueOf(o),field.getType()));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private Object conver(String value,Class clazz){
        Object object;
        switch (clazz.getName()) {
            case "byte" :
                object = Byte.valueOf(value);
                break;
            case "short" :
                object = Short.parseShort(value);
                break;
            case "int" :
                object = Integer.valueOf(value);
                break;
            case "float" :
                object = Float.parseFloat(value);
                break;
            case "long" :
                object = Long.parseLong(value);
                break;
            case "double" :
                object = Double.parseDouble(value);
                break;
            case "boolean" :
                object = Boolean.parseBoolean(value);
                break;
            default :
                object = String.valueOf(value);
                break;
        }
        return object;
    }
}
